import 'dart:convert';
import 'dart:io';
import 'package:flutter/services.dart';
import 'EmojiOne.dart';

class EmojiOneInfoes {

  static EmojiOneInfoes INSTANCE = new EmojiOneInfoes();

  Map<String, EmojiOne> _EMOJI_UNICODE_MAP = Map<String, EmojiOne>();
  Map<String, EmojiOne> _EMOJI_MAP = Map<String, EmojiOne>();
  Map<String, List<EmojiOne>> _EMOJI_CATEGORY_MAP = Map<String, List<EmojiOne>>();

  EmojiOneInfoes();

  static EmojiOneInfoes getInstance() {
    EmojiOneInfoes instance = EmojiOneInfoes.INSTANCE;
    return instance;
  }

  List<EmojiOne> emojiFromCategory(String category) {
    if (_EMOJI_UNICODE_MAP.length < 1) {
      loadData();
    }
    if (_EMOJI_CATEGORY_MAP.containsKey(category)) {
      return _EMOJI_CATEGORY_MAP[category]!;
    }
    var result = <EmojiOne>[];
    for (var value in _EMOJI_MAP.values) {
      var emojiCategory = value.category!;
      var isEqual = category.indexOf(emojiCategory)>=0;
      if (isEqual) {
        result.add(value);
      }
    }
    result.sort((a, b)=>a.emoji_order??0-(b.emoji_order??0));
    return result;
  }

  List<EmojiOne> getAllEmojiOnes() {
    if (_EMOJI_UNICODE_MAP.length < 1) {
      loadData();
    }
    return _EMOJI_UNICODE_MAP.values.toList(growable: false);
  }

  EmojiOne? getEmojiOne(String resource) {
    var lasted = resource.lastIndexOf("/");
    if (lasted > 0) {
      var name = resource.substring(lasted +1);
      var unicode = name.substring(0, name.length - 4);
      return _EMOJI_UNICODE_MAP[unicode]!;
    }
    return null;
  }

  EmojiOne? getByUnicode(String unicode) {
    return _EMOJI_UNICODE_MAP[unicode];
  }

  EmojiOne? getByUnicodeOrShortName(String unicode) {
    var emoji = _EMOJI_UNICODE_MAP[unicode];
    if (emoji != null) {
      return emoji;
    }
    emoji = _EMOJI_MAP[unicode];
    if (emoji != null) {
      return emoji;
    }
    emoji = _EMOJI_MAP[":" + unicode + ":"];
    return emoji;
  }

  EmojiOne? emojiFromCodepoints(String codePoint) {
    if (_EMOJI_UNICODE_MAP.containsKey(codePoint)) {
      return _EMOJI_UNICODE_MAP[codePoint]!;
    }
    if (_EMOJI_UNICODE_MAP.containsKey(codePoint + "-FE0F")) {
      return _EMOJI_UNICODE_MAP[(codePoint + "-FE0F")];
    }
    return null;
  }

  static Future<String> loadEmojiJson() async {
    String fileUrl = "assets/emojione/emoji.json";
    print("emojione file : $fileUrl");
    if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
      File file = File(fileUrl);
      var json = file.readAsStringSync();
      // print("emojione init : $json");
      return json;
    } else {
      var json = await rootBundle.loadString(fileUrl);
      print("emojione init : $json");
      return json;
    }
  }

  loadData() async {
    try {
      var content = await loadEmojiJson();
      var emojiOneObject = jsonDecode(content);
      for (var obj in emojiOneObject.values.toList()) {
        // print("emoji: ${obj}");
        EmojiOne emojiOne = EmojiOne.fromJson(obj);
        _EMOJI_UNICODE_MAP[emojiOne.unicode] = emojiOne;
        _EMOJI_MAP[emojiOne.shortname] = emojiOne;
        // print('emoji: ' + emojiOne.shortname);
      }

      _categoryEmoji();

      print("emoji size: ${_EMOJI_UNICODE_MAP.length}");
    } catch (error) {
      print("load emoji json file error: " +  error.toString());
    }
  }

  _categoryEmoji() {
    for (var value in _EMOJI_MAP.values) {
      var emojiCategory = value.category!;
      var categoryList = _EMOJI_CATEGORY_MAP[emojiCategory];
      if (categoryList == null) {
        categoryList = <EmojiOne>[];
        _EMOJI_CATEGORY_MAP[emojiCategory] = categoryList;
      }
      categoryList.add(value);
    }
    for(var key in _EMOJI_CATEGORY_MAP.keys) {
      var values = _EMOJI_CATEGORY_MAP[key];
      values!.sort((a, b)=>a.emoji_order??0-(b.emoji_order??0));
      _EMOJI_CATEGORY_MAP[key] = values;
    }
  }
}
